package com.unitd.base.frame.util;

import com.google.common.collect.Maps;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 日期工具类
 *
 * @author Hudan
 * @version 1.0
 * @filename DateUtils.java
 * @copyright www.unitd.com
 * @date 2019-01-23
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

    public static final String DATE_PATTERN = "yyyy-MM-dd";
    public static final String MONTH_PATTERN = "yyyy-MM";
    public static final String TIMESTAMP_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String DAY_STR = "yyyyMMdd";
    public static final String STAMP_STR = "HHmmss";
    public static final String TIMESTAMP_STR = "yyyyMMddHHmmss";
    public static final String TIMESTAMP_SECOND_STR = "yyyyMMddHHmmssSSS";
    private static final Object timestampFormatLock = new Object();
    private static final Map<String, ThreadLocal<SimpleDateFormat>> timestampFormatPool = Maps.newHashMap();

    /**
     * 获取格式化时间对象
     *
     * @return SimpleDateFormat
     */
    private static SimpleDateFormat getTimestampFormat() {
        ThreadLocal<SimpleDateFormat> thread = timestampFormatPool.get(TIMESTAMP_PATTERN);
        if (null == thread) {
            synchronized (timestampFormatLock) {
                thread = timestampFormatPool.get(TIMESTAMP_PATTERN);
                if (null == thread) {
                    thread = new ThreadLocal<SimpleDateFormat>() {
                        @Override
                        protected synchronized SimpleDateFormat initialValue() {
                            return new SimpleDateFormat(TIMESTAMP_PATTERN);
                        }
                    };
                    timestampFormatPool.put(TIMESTAMP_PATTERN, thread);
                }
            }
        }
        return thread.get();
    }

    /**
     * 根据制定的时间格式, 获取该格式下的当前时间对象
     *
     * @return 当前时间对象
     */
    public static Date getCurrDate() {
        return getCurrDate(null);
    }

    /**
     * 根据制定的时间格式, 获取该格式下的当前时间对象
     *
     * @param formater 支持的时间格式
     * @return 当前时间对象
     */
    public static Date getCurrDate(String formater) {
        Date currDate = null;
        try {
            if (StringUtils.isNull(formater)) {
                formater = TIMESTAMP_PATTERN;
            }

            SimpleDateFormat sdf = new SimpleDateFormat(formater);
            currDate = sdf.parse(sdf.format(new Date()));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return currDate;
    }

    /**
     * 根据制定的时间格式, 获取该格式下的当前时间字符串
     *
     * @param formater 支持的时间格式
     * @return 时间字符串
     */
    public static String getCurrTime(String formater) {
        return new SimpleDateFormat(formater).format(new Date());
    }

    /**
     * 将时间加上或者减去seconds秒
     *
     * @param date    日期
     * @param seconds 秒数
     * @return
     */
    public static Date calculateDate(Date date, int seconds) {
        if (date == null) {
            return null;
        }
        long time = seconds * 1000;
        return new Date(date.getTime() + time);
    }

    /**
     * 获取一天开始时间
     *
     * @param date 指定日期
     * @return Date
     */
    public static Date getDayBegin(Date date) {
        String format = DateFormatUtils.format(date, DATE_PATTERN);
        return parseDate(format.concat(" 00:00:00"));
    }

    /**
     * 获取一天结束时间
     *
     * @param date 指定日期
     * @return Date
     */
    public static Date getDayEnd(Date date) {
        String format = DateFormatUtils.format(date, DATE_PATTERN);
        return parseDate(format.concat(" 23:59:59"));
    }


    /**
     * 比较两个时间相差多少秒
     *
     * @param start 需要比较的开始时间
     * @param end   需要比较的结束时间
     * @return
     */
    public static long getDiffSeconds(Date start, Date end) {
        return Math.abs((end.getTime() - start.getTime()) / 1000);
    }

    /**
     * @param start 需要比较的开始时间
     * @param end   需要比较的结束时间
     * @return 比较两个时间相差多少分钟
     */
    public static long getDiffMinutes(Date start, Date end) {
        long diffSeconds = getDiffSeconds(start, end);
        return diffSeconds / 60;
    }

    /**
     * 比较两个时间相差多少天
     *
     * @param start 需要比较的开始时间
     * @param end   需要比较的结束时间
     * @return
     */
    public static long getDiffDay(Date start, Date end) {
        long between = Math.abs((end.getTime() - start.getTime()) / 1000);
        long day = between / 60 / 60 / 24;
        return (long) Math.floor(day);
    }

    /**
     * 获取两个时间相差月份
     *
     * @param start 需要比较的开始时间
     * @param end   需要比较的结束时间
     * @return
     */
    public static int getDiffMonth(Date start, Date end) {
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(start);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(end);
        return (endCalendar.get(Calendar.YEAR) - startCalendar.get(Calendar.YEAR)) * 12
                + endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH);
    }

    /**
     * 格式化日期为日期字符串
     *
     * @param date     时间对象
     * @param patterns 指定的时间格式
     * @return 指定格式的时间字符串
     */
    public static String format(Date date, String... patterns) {
        if (date == null) {
            return "";
        }

        String pattern = TIMESTAMP_PATTERN;
        if (patterns != null && patterns.length > 0
                && org.apache.commons.lang3.StringUtils.isNotBlank(patterns[0])) {
            pattern = patterns[0];
        }
        return DateFormatUtils.format(date, pattern);
    }

    /**
     * 格式化日期为指定格式
     *
     * @param orig     需要格式化的时间对象
     * @param patterns 日期格式
     * @return Date
     */
    public static Date formatDate(Date orig, String... patterns) {
        if (orig == null) {
            return null;
        }

        String pattern = TIMESTAMP_PATTERN;
        if (patterns != null && patterns.length > 0
                && StringUtils.isNotBlank(patterns[0])) {
            pattern = patterns[0];
        }
        return parseDate(DateFormatUtils.format(orig, pattern));
    }

    /**
     * 格式化日期字符串
     *
     * @param dateStr  日期字符串
     * @param patterns 日期格式
     * @return
     */
    public static String formatDateStr(String dateStr, String... patterns) {
        String pattern = TIMESTAMP_PATTERN;
        if (patterns != null && patterns.length > 0
                && StringUtils.isNotBlank(patterns[0])) {
            pattern = patterns[0];
        }
        return DateFormatUtils.format(parseDate(dateStr), pattern);
    }

    /**
     * 格式化日期为日期字符串
     *
     * @param date     时间对象
     * @param patterns 日期格式
     * @return
     */
    public static String format2DateStr(Date date, String... patterns) {
        if (date == null) {
            return "";
        }

        String pattern = TIMESTAMP_PATTERN;
        if (patterns != null && patterns.length > 0
                && StringUtils.isNotBlank(patterns[0])) {
            pattern = patterns[0];
        }
        return DateFormatUtils.format(date, pattern);
    }

    /**
     * 时间戳格式转换为日期（年月日 yyyy-MM-dd）格式
     *
     * @param date 时间戳格式时间对象
     * @return
     */
    public static Date timestamp2Date(Date date) {
        return formatDate(date, DATE_PATTERN);
    }

    /**
     * @param formater 支持的时间格式
     * @return Date
     * 按照指定的时间格式, 解析日期获取对应的格式后的时间对象
     */
    public static Date parseDate(String formater) {
        SimpleDateFormat format;
        if (StringUtils.isBlank(formater)) {
            return null;
        }

        formater = formater.trim();
        try {
            if (formater.matches("\\d{1,2}[A-Z]{3}")) {
                formater = formater
                        + (Calendar.getInstance().get(Calendar.YEAR) - 2000);
            }
            // 01OCT12
            if (formater.matches("\\d{1,2}[A-Z]{3}\\d{2}")) {
                format = new SimpleDateFormat("ddMMMyy", Locale.ENGLISH);
            } else if (formater.matches("\\d{1,2}[A-Z]{3}\\d{4}.*")) {
                // 01OCT2012,01OCT2012 1224,01OCT2012 12:24
                formater = formater.replaceAll("[^0-9A-Z]", "")
                        .concat("000000").substring(0, 15);
                format = new SimpleDateFormat("ddMMMyyyyHHmmss", Locale.ENGLISH);
            } else {
                StringBuffer sb = new StringBuffer(formater);
                String[] tempArr = formater.split("\\s+");
                tempArr = tempArr[0].split("-|\\/");
                if (tempArr.length == 3) {
                    if (tempArr[1].length() == 1) {
                        sb.insert(5, "0");
                    }
                    if (tempArr[2].length() == 1) {
                        sb.insert(8, "0");
                    }
                }
                formater = sb.append("000000").toString().replaceAll("[^0-9]",
                        "").substring(0, 14);
                if (formater.matches("\\d{14}")) {
                    format = new SimpleDateFormat("yyyyMMddHHmmss");
                } else {
                    format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                }
            }
            return format.parse(formater);
        } catch (Exception e) {
            throw new RuntimeException("无法解析日期字符[" + formater + "]");
        }
    }

    /**
     * 判断两个日期的大小，end减start，等于1代表end大于start，等于0代表相等，等于-1代表小于
     *
     * @param start
     * @param end
     * @return
     */
    public static int compareDate(Date start, Date end) {
        if (start == null || end == null) {
            return -2;
        }
        if (end.getTime() > start.getTime()) {
            return 1;
        } else if (end.getTime() == start.getTime()) {
            return 0;
        } else {
            return -1;
        }
    }

    public static Date stringToDate(String dateStr, String formater) {
        if (StringUtils.isNull(dateStr)) {
            return null;
        }
        Date date = null;
        SimpleDateFormat sdf = new SimpleDateFormat(formater);
        try {
            date = sdf.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

}